package graphics;

import graphics.UsefulFunctions.FHR;

import org.javia.arity.Function;

public class RendererFlat extends AbsRenderer {

	Function func;

	public RendererFlat(int height, int width, Function f) {
		func = f;

	}

	public void render(int height, int width, StatesCapsule sC)
	// Regular floating horizon - no shading
	// ======================================
	{
		tmp_height = height;
		FHR fhr[];
		float z, X, Y; // , xtag, ytag, ztag;
		float zsa, zca, zsb, zcb;
		int XS, YS, firstXS, lastXS;

		float r1, u, v, w, y1, z1;
		float xtag, ytag, ztag;

		screen = new int[height + 1][width + 1]; // virtual screen
		// System.out.println("Flat: " + height + "," + width);
		firstXS = sC.getMidx()
				+ (int) (-sC.getRADIUS() * sC.getScreen_to_max_crd_ratio());
		lastXS = sC.getMidx()
				+ (int) (sC.getRADIUS() * sC.getScreen_to_max_crd_ratio());

		fhr = new FHR[1024];
		for (int i = 0; i < 1024; ++i)
			fhr[i] = new FHR();

		for (z = sC.getNeg_t_plane_limit(); z <= sC.getPos_t_plane_limit(); z += sC
				.getT_STEP()) {
			zsb = z * sC.getSin_beta();
			zcb = z * sC.getCos_beta();
			zsa = z * sC.getSin_alpha();
			zca = z * sC.getCos_alpha();
			if (sC.getFUN_MAX() * sC.getSin_alpha() + zca <= -sC
					.getDist_of_screen_from_origin())
				continue;

			for (XS = firstXS; XS <= lastXS; XS++) {

				X = (XS - sC.getMidx()) / sC.getScreen_to_max_crd_ratio();
				xtag = X * sC.getCos_beta() + zsb;
				ztag = -X * sC.getSin_beta() + zcb;
				ytag = (float) func.eval(xtag, ztag); // calculate function
				Y = ytag * sC.getCos_alpha() - zsa;
				r1 = X * (zca + sC.getDist_of_veiwport_from_origin())
						/ sC.getDist_veiwport_from_screen();
				u = r1 * sC.getCos_beta() + zsb;
				v = -r1 * sC.getSin_beta() + zcb;
				w = (float) func.eval(u, v);
				

					y1 = w * sC.getCos_alpha() - zsa;
					z1 = w * sC.getSin_alpha() + zca;
			if (sC.isPerspective) 
				Y = y1 * sC.getDist_veiwport_from_screen()
						/ (z1 + sC.getDist_of_veiwport_from_origin());
			else
				Y = y1;
			
				YS = (int) UsefulFunctions.my_Round(Y
						* sC.getScreen_to_max_crd_ratio() + sC.getMidy());

				if (YS < 0)
					YS = -1; // don't waste time on
				if (YS > sC.getMaxy())
					YS = sC.getMaxy() + 1; // invisible pixels
				if (fhr[XS].ymin == Integer.MAX_VALUE
						&& fhr[XS].ymax == Integer.MIN_VALUE) { // First pixel
																// in column:
					fhr[XS].ymin = fhr[XS].ymax = fhr[XS].yprev = YS;
					if (XS == firstXS) // check if first column
						Putpixel(XS, YS, 0, 0.0f);
					else
						// draw line segment for continuity
						Line(XS - 1, fhr[XS - 1].yprev, XS, YS);
				} else // not first pixel in column - check if visible:
				{
					if (YS < fhr[XS].ymin) // below minimum for column
					{
						fhr[XS].ymin = fhr[XS].yprev = YS;
						if (XS == firstXS) // check if first column
							Putpixel(XS, YS, 0, 0.0f);
						else
							// draw line segment for continuity
							Line(XS - 1, fhr[XS - 1].ymin, XS, YS);
					} else if (YS > fhr[XS].ymax) // above maximum for column
					{
						fhr[XS].ymax = fhr[XS].yprev = YS;
						if (XS == firstXS) // check if first column
							Putpixel(XS, YS, 0, 0.0f);
						else
							// draw line segment for continuity
							Line(XS - 1, fhr[XS - 1].ymax, XS, YS);
					} else if (XS > firstXS) // check if partial line needed:
					{
						if (fhr[XS - 1].yprev > fhr[XS].ymax)
							Line(XS - 1, fhr[XS - 1].yprev, XS, fhr[XS].ymax);
						else if (fhr[XS - 1].yprev < fhr[XS].ymin)
							Line(XS - 1, fhr[XS - 1].yprev, XS, fhr[XS].ymin);
					}
				}
			} // of x axis for
		} // of z axis for
	} // end of flh_regular

}
